package JackSu.java01;

import java.util.Random;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicLong;

/**
 * RandomTest
 *
 * @author Syzer
 * @Description 定义
 * @Date 2021/3/10
 */
public class RandomTest {

    public static void main(String[] args) {
        Random random = new Random();
        int a = random.nextInt(10);
        int b = random.nextInt(10);
        int c = random.nextInt(10);
        int d = random.nextInt(10);
        int e = random.nextInt(10);
        int f = random.nextInt(10);
        int g = random.nextInt(10);
        int h = random.nextInt(10);
        int i = random.nextInt(10);
        int j = random.nextInt(10);
        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
        System.out.println(d);
        System.out.println(e);
        System.out.println(f);
        System.out.println(g);
        System.out.println(h);
        System.out.println(i);
        System.out.println(j);
        System.out.println("--------------");
        a = nextInt(10, new AtomicLong(163383441927212L));
        b = nextInt(10, new AtomicLong(163383441927213L));
        c = nextInt(10, new AtomicLong(163383441927214L));
        d = nextInt(10, new AtomicLong(163383441927215L));
        e = nextInt(10, new AtomicLong(163383441927216L));
        f = nextInt(10, new AtomicLong(163383441927217L));
        g = nextInt(10, new AtomicLong(163383441927218L));
        h = nextInt(10, new AtomicLong(163383441927219L));
        i = nextInt(10, new AtomicLong(163383441927220L));
        j = nextInt(10, new AtomicLong(163383441927221L));
        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
        System.out.println(d);
        System.out.println(e);
        System.out.println(f);
        System.out.println(g);
        System.out.println(h);
        System.out.println(i);
        System.out.println(j);
        System.out.println("--------------");
        a = nextInt_163383441927212(10);
        b = nextInt_163383441927212(10);
        c = nextInt_163383441927212(10);
        d = nextInt_163383441927212(10);
        e = nextInt_163383441927212(10);
        f = nextInt_163383441927212(10);
        g = nextInt_163383441927212(10);
        h = nextInt_163383441927212(10);
        i = nextInt_163383441927212(10);
        j = nextInt_163383441927212(10);
        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
        System.out.println(d);
        System.out.println(e);
        System.out.println(f);
        System.out.println(g);
        System.out.println(h);
        System.out.println(i);
        System.out.println(j);
        System.out.println(8006946109359709005L * 2521494123412341234L);
        ThreadLocalRandom current = ThreadLocalRandom.current();
        current.nextInt(12);
//        System.out.println(121049056512526L - 121023841608609L);
//        System.out.println(121023841608609L - 120998626704692L);
//        System.out.println(120998626704692L - 120973411800775L);
//        System.out.println(923531009 - 923338635);
//        System.out.println(923338635 - 923146260);
//        System.out.println(923146260 - 922953886);
//        System.out.println(923723384 - 923531009);
//        System.out.println(923915758 - 923723384);
//        System.out.println(924108133 - 923915758);
//        System.out.println(924300507 - 924108133);

    }

    private static final AtomicLong seed = new AtomicLong(163383441927212L);

    private static final AtomicLong seedUniquifier
            = new AtomicLong(8682522807148012L);

    private static long seedUniquifier() {
        for (;;) {
            long current = seedUniquifier.get();
            long next = current * 181783497276652981L;
            //多线程情况下，执行seedUniquifier.get()后，调用compareAndSet方法前，另一线程调用以下set方法将判断版本不一致造成死循环。
//            seedUniquifier.set(123L);
            if (seedUniquifier.compareAndSet(current, next))
                return next;
        }
    }

    public static int nextInt(int bound, AtomicLong paramSeed) {
        int r = next(31, paramSeed);
        int m = bound - 1;
        if ((bound & m) == 0)  // i.e., bound is a power of 2
            r = (int)((bound * (long)r) >> 31);
        else {
            for (int u = r; u - (r = u % bound) + m < 0; u = next(31, paramSeed)){
                System.out.println(u);
            }
        }
        return r;
    }

    public static int nextInt_163383441927212(int bound) {
        int r = next_163383441927212(31);
        int m = bound - 1;
        if ((bound & m) == 0)  // i.e., bound is a power of 2
            r = (int)((bound * (long)r) >> 31);
        else {
            for (int u = r; u - (r = u % bound) + m < 0; u = next_163383441927212(31)){
                System.out.println(u);
            }
        }
        return r;
    }

    protected static int next(int bits, AtomicLong paramSeed) {
        long oldseed, nextseed;
        AtomicLong seed = paramSeed;
        do {
            oldseed = seed.get();
            nextseed = (oldseed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
        } while (!seed.compareAndSet(oldseed, nextseed));
        return (int)(nextseed >>> (48 - bits));
    }

    protected static int next_163383441927212(int bits) {
        long oldseed, nextseed;
        AtomicLong seed = RandomTest.seed;
        do {
            oldseed = seed.get();
            nextseed = (oldseed * 0x5DEECE66DL + 0xBL) & ((1L << 48) - 1);
        } while (!seed.compareAndSet(oldseed, nextseed));
        return (int)(nextseed >>> (48 - bits));
    }
}
